home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac: Not for Sale / Another.not.for.sale (Australia).iso / hold me in your arms / PGP 2.6 / rsaref Toolkit / source / r_enhanc.c < prev    next >
C/C++ Source or Header  |  1992-02-29  |  18KB  |  517 lines

  1. /* R_ENHANC.C - cryptographic enhancements for RSAREF
  2.  */
  3.  
  4. /* Copyright (C) 1991-2 RSA Laboratories, a division of RSA Data
  5.    Security, Inc. All rights reserved.
  6.  */
  7.  
  8. #include "global.h"
  9. #include "rsaref.h"
  10. #include "r_encode.h"
  11. #include "r_random.h"
  12. #include "rsa.h"
  13. #include "md2.h"
  14. #include "md5.h"
  15. #include "des.h"
  16.  
  17. /* DigestInfo encoding is DIGEST_INFO_A, then 2 or 5 (for MD2/MD5),
  18.    then DIGEST_INFO_B, then 16-byte message digest.
  19.  */
  20.  
  21. static char DIGEST_INFO_A[] = {
  22.   0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7,
  23.   0x0d, 0x02
  24. };
  25. #define DIGEST_INFO_A_LEN sizeof (DIGEST_INFO_A)
  26.  
  27. static char DIGEST_INFO_B[] = { 0x05, 0x00, 0x04, 0x10 };
  28. #define DIGEST_INFO_B_LEN sizeof (DIGEST_INFO_B)
  29.  
  30. #define DIGEST_INFO_LEN (DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN + 16)
  31.  
  32. static unsigned char *PADDING[] = {
  33.   (unsigned char *)"", (unsigned char *)"\001", (unsigned char *)"\002\002",
  34.   (unsigned char *)"\003\003\003", (unsigned char *)"\004\004\004\004",
  35.   (unsigned char *)"\005\005\005\005\005",
  36.   (unsigned char *)"\006\006\006\006\006\006", 
  37.   (unsigned char *)"\007\007\007\007\007\007\007",
  38.   (unsigned char *)"\010\010\010\010\010\010\010\010"
  39. };
  40.  
  41. #define MAX_ENCRYPTED_KEY_LEN MAX_RSA_MODULUS_LEN
  42.  
  43. static int R_SignBlock PROTO_LIST 
  44.   ((unsigned char *, unsigned int *, unsigned char *, unsigned int, int,
  45.     R_RSA_PRIVATE_KEY *));
  46. static void R_EncodeDigestInfo PROTO_LIST
  47.   ((unsigned char *, int, unsigned char *));
  48. static void R_EncryptPEMBlock PROTO_LIST
  49.   ((unsigned char *, unsigned int *, unsigned char *, unsigned int,
  50.     unsigned char [8], unsigned char [8]));
  51. static int R_DecryptPEMBlock PROTO_LIST
  52.   ((unsigned char *, unsigned int *, unsigned char *, unsigned int,
  53.     unsigned char [8], unsigned char [8]));
  54.  
  55. int R_SignPEMBlock 
  56.   (encodedContent, encodedContentLen, encodedSignature, encodedSignatureLen,
  57.    content, contentLen, recode, digestAlgorithm, privateKey)
  58. unsigned char *encodedContent;                           /* encoded content */
  59. unsigned int *encodedContentLen;               /* length of encoded content */
  60. unsigned char *encodedSignature;                       /* encoded signature */
  61. unsigned int *encodedSignatureLen;           /* length of encoded signature */
  62. unsigned char *content;                                          /* content */
  63. unsigned int contentLen;                               /* length of content */
  64. int recode;                                                /* recoding flag */
  65. int digestAlgorithm;                            /* message-digest algorithm */
  66. R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
  67. {
  68.   int status;
  69.   unsigned char signature[MAX_SIGNATURE_LEN];
  70.   unsigned int signatureLen;
  71.   
  72.   if (status = R_SignBlock
  73.       (signature, &signatureLen, content, contentLen, digestAlgorithm,
  74.        privateKey))
  75.     return (status);
  76.  
  77.   R_EncodePEMBlock 
  78.     (encodedSignature, encodedSignatureLen, signature, signatureLen);
  79.  
  80.   if (recode)
  81.     R_EncodePEMBlock
  82.     (encodedContent, encodedContentLen, content, contentLen);
  83.  
  84.   return (0);
  85. }
  86.  
  87. int R_VerifyPEMSignature 
  88.   (content, contentLen, encodedContent, encodedContentLen, encodedSignature,
  89.    encodedSignatureLen, recode, digestAlgorithm, publicKey)
  90. unsigned char *content;                                          /* content */
  91. unsigned int *contentLen;                              /* length of content */
  92. unsigned char *encodedContent;                /* (possibly) encoded content */
  93. unsigned int encodedContentLen;                /* length of encoded content */
  94. unsigned char *encodedSignature;                       /* encoded signature */
  95. unsigned int encodedSignatureLen;            /* length of encoded signature */
  96. int recode;                                                /* recoding flag */
  97. int digestAlgorithm;                            /* message-digest algorithm */
  98. R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
  99. {
  100.   int status;
  101.   unsigned char signature[MAX_SIGNATURE_LEN];
  102.   unsigned int signatureLen;
  103.   
  104.   if (encodedSignatureLen > MAX_PEM_SIGNATURE_LEN)
  105.     return (RE_SIGNATURE_ENCODING);
  106.   
  107.   if (recode) {
  108.     if (status = R_DecodePEMBlock
  109.         (content, contentLen, encodedContent, encodedContentLen))
  110.       return (RE_CONTENT_ENCODING);
  111.   }
  112.   else {
  113.     content = encodedContent;
  114.     *contentLen = encodedContentLen;
  115.   }
  116.     
  117.   if (status = R_DecodePEMBlock
  118.       (signature, &signatureLen, encodedSignature, encodedSignatureLen))
  119.     return (RE_SIGNATURE_ENCODING);
  120.   
  121.   return (R_VerifyBlockSignature 
  122.           (content, *contentLen, signature, signatureLen, digestAlgorithm,
  123.            publicKey));
  124. }
  125.  
  126. int R_VerifyBlockSignature 
  127.   (block, blockLen, signature, signatureLen, digestAlgorithm, publicKey)
  128. unsigned char *block;                                              /* block */
  129. unsigned int blockLen;                                   /* length of block */
  130. unsigned char *signature;                                      /* signature */
  131. unsigned int signatureLen;                           /* length of signature */
  132. int digestAlgorithm;                            /* message-digest algorithm */
  133. R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
  134. {
  135.   int status;
  136.   unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN],
  137.     originalDigestInfo[MAX_SIGNATURE_LEN];
  138.   unsigned int digestLen, originalDigestInfoLen;
  139.   
  140.   if (signatureLen > MAX_SIGNATURE_LEN)
  141.     return (RE_SIGNATURE);
  142.   
  143.   do {
  144.     if (status = R_DigestBlock 
  145.         (digest, &digestLen, block, blockLen, digestAlgorithm))
  146.       break;
  147.     
  148.     R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest);
  149.     
  150.     if (status = RSAPublicDecrypt
  151.         (originalDigestInfo, &originalDigestInfoLen, signature, signatureLen, 
  152.          publicKey)) {
  153.       status = RE_PUBLIC_KEY;
  154.       break;
  155.     }
  156.     
  157.     if ((originalDigestInfoLen != DIGEST_INFO_LEN) ||
  158.         (R_memcmp 
  159.          ((POINTER)originalDigestInfo, (POINTER)digestInfo,
  160.           DIGEST_INFO_LEN))) {
  161.       status = RE_SIGNATURE;
  162.       break;
  163.     }
  164.  
  165.   } while (0);
  166.   
  167.   /* Zeroize potentially sensitive information.
  168.    */
  169.   R_memset ((POINTER)digest, 0, sizeof (digest));
  170.   R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
  171.   R_memset ((POINTER)originalDigestInfo, 0, sizeof (originalDigestInfo));
  172.  
  173.   return (status);
  174. }
  175.  
  176. int R_SealPEMBlock 
  177.   (encryptedContent, encryptedContentLen, encryptedKey, encryptedKeyLen,
  178.    encryptedSignature, encryptedSignatureLen, iv, content, contentLen,
  179.    digestAlgorithm, publicKey, privateKey, randomStruct)
  180. unsigned char *encryptedContent;              /* encoded, encrypted content */
  181. unsigned int *encryptedContentLen;                                /* length */
  182. unsigned char *encryptedKey;                      /* encoded, encrypted key */
  183. unsigned int *encryptedKeyLen;                                    /* length */
  184. unsigned char *encryptedSignature;          /* encoded, encrypted signature */
  185. unsigned int *encryptedSignatureLen;                              /* length */
  186. unsigned char iv[8];                             /* DES initializing vector */
  187. unsigned char *content;                                          /* content */
  188. unsigned int contentLen;                               /* length of content */
  189. int digestAlgorithm;                            /* message-digest algorithm */
  190. R_RSA_PUBLIC_KEY *publicKey;                  /* recipient's RSA public key */
  191. R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
  192. R_RANDOM_STRUCT *randomStruct;                          /* random structure */
  193. {
  194.   int status;
  195.   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN], key[8],
  196.     signature[MAX_SIGNATURE_LEN];
  197.   unsigned int encryptedKeyBlockLen, signatureLen;
  198.   
  199.   do {
  200.     if (status = R_SignBlock
  201.         (signature, &signatureLen, content, contentLen, digestAlgorithm,
  202.          privateKey))
  203.       break;
  204.     
  205.     if ((status = R_GenerateBytes (key, 8, randomStruct)) ||
  206.         (status = R_GenerateBytes (iv, 8, randomStruct)))
  207.       break;
  208.  
  209.     R_EncryptPEMBlock 
  210.       (encryptedContent, encryptedContentLen, content, contentLen, key, iv);
  211.     
  212.     if (status = RSAPublicEncrypt
  213.         (encryptedKeyBlock, &encryptedKeyBlockLen, key, 8, publicKey,
  214.          randomStruct)) {
  215.       status = RE_PUBLIC_KEY;
  216.       break;
  217.     }
  218.     
  219.     R_EncodePEMBlock 
  220.       (encryptedKey, encryptedKeyLen, encryptedKeyBlock,
  221.        encryptedKeyBlockLen);
  222.  
  223.     R_EncryptPEMBlock
  224.       (encryptedSignature, encryptedSignatureLen, signature, signatureLen,
  225.        key, iv);
  226.  
  227.   } while (0);
  228.   
  229.   /* Zeroize sensitive information.
  230.    */
  231.   R_memset ((POINTER)key, 0, sizeof (key));
  232.   R_memset ((POINTER)signature, 0, sizeof (signature));
  233.  
  234.   return (status);
  235. }
  236.  
  237. int R_OpenPEMBlock
  238.   (content, contentLen, encryptedContent, encryptedContentLen, encryptedKey,
  239.    encryptedKeyLen, encryptedSignature, encryptedSignatureLen,
  240.    iv, digestAlgorithm, privateKey, publicKey)
  241. unsigned char *content;                                          /* content */
  242. unsigned int *contentLen;                              /* length of content */
  243. unsigned char *encryptedContent;              /* encoded, encrypted content */
  244. unsigned int encryptedContentLen;                                 /* length */
  245. unsigned char *encryptedKey;                      /* encoded, encrypted key */
  246. unsigned int encryptedKeyLen;                                     /* length */
  247. unsigned char *encryptedSignature;          /* encoded, encrypted signature */
  248. unsigned int encryptedSignatureLen;                               /* length */
  249. unsigned char iv[8];                             /* DES initializing vector */
  250. int digestAlgorithm;                            /* message-digest algorithm */
  251. R_RSA_PRIVATE_KEY *privateKey;               /* recipient's RSA private key */
  252. R_RSA_PUBLIC_KEY *publicKey;                     /* signer's RSA public key */
  253. {
  254.   int status;
  255.   unsigned char encryptedKeyBlock[MAX_ENCRYPTED_KEY_LEN],
  256.     key[MAX_ENCRYPTED_KEY_LEN], signature[MAX_SIGNATURE_LEN];
  257.   unsigned int encryptedKeyBlockLen, keyLen, signatureLen;
  258.   
  259.   if (encryptedKeyLen > MAX_PEM_ENCRYPTED_KEY_LEN)
  260.     return (RE_KEY_ENCODING);
  261.   
  262.   if (encryptedSignatureLen > MAX_PEM_ENCRYPTED_SIGNATURE_LEN)
  263.     return (RE_SIGNATURE_ENCODING);
  264.   
  265.   do {
  266.     if (status = R_DecodePEMBlock 
  267.         (encryptedKeyBlock, &encryptedKeyBlockLen, encryptedKey,
  268.          encryptedKeyLen)) {
  269.       status = RE_KEY_ENCODING;
  270.       break;
  271.     }
  272.  
  273.     if (status = RSAPrivateDecrypt
  274.         (key, &keyLen, encryptedKeyBlock, encryptedKeyBlockLen, privateKey)) {
  275.       status = RE_PRIVATE_KEY;
  276.       break;
  277.     }
  278.     
  279.     if (keyLen != 8) {
  280.       status = RE_PRIVATE_KEY;
  281.       break;
  282.     }
  283.     
  284.     if (status = R_DecryptPEMBlock 
  285.         (content, contentLen, encryptedContent, encryptedContentLen, key,
  286.          iv)) {
  287.       if ((status == RE_LEN || status == RE_ENCODING))
  288.         status = RE_CONTENT_ENCODING;
  289.       else
  290.         status = RE_KEY;
  291.       break;
  292.     }
  293.     
  294.     if (status = R_DecryptPEMBlock
  295.         (signature, &signatureLen, encryptedSignature, encryptedSignatureLen,
  296.          key, iv)) {
  297.       if ((status == RE_LEN || status == RE_ENCODING))
  298.         status = RE_SIGNATURE_ENCODING;
  299.       else
  300.         status = RE_KEY;
  301.     }
  302.  
  303.     if (status = R_VerifyBlockSignature
  304.         (content, *contentLen, signature, signatureLen, digestAlgorithm,
  305.          publicKey))
  306.       break;
  307.  
  308.   } while (0);
  309.   
  310.   /* Zeroize sensitive information.
  311.    */
  312.   R_memset ((POINTER)key, 0, sizeof (key));
  313.   R_memset ((POINTER)signature, 0, sizeof (signature));
  314.  
  315.   return (status);
  316. }
  317.  
  318. static int R_SignBlock
  319.   (signature, signatureLen, block, blockLen, digestAlgorithm, privateKey)
  320. unsigned char *signature;                                      /* signature */
  321. unsigned int *signatureLen;                          /* length of signature */
  322. unsigned char *block;                                              /* block */
  323. unsigned int blockLen;                                   /* length of block */
  324. int digestAlgorithm;                            /* message-digest algorithm */
  325. R_RSA_PRIVATE_KEY *privateKey;                  /* signer's RSA private key */
  326. {
  327.   int status;
  328.   unsigned char digest[MAX_DIGEST_LEN], digestInfo[DIGEST_INFO_LEN];
  329.   unsigned int digestLen;
  330.  
  331.   do {
  332.     if (status = R_DigestBlock
  333.         (digest, &digestLen, block, blockLen, digestAlgorithm))
  334.       break;
  335.     
  336.     R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest);
  337.     
  338.     if (status = RSAPrivateEncrypt
  339.         (signature, signatureLen, digestInfo, DIGEST_INFO_LEN, privateKey)) {
  340.       status = RE_PRIVATE_KEY;
  341.       break;
  342.     }
  343.  
  344.   } while (0);
  345.   
  346.   /* Zeroize potentially sensitive information.
  347.    */
  348.   R_memset ((POINTER)digest, 0, sizeof (digest));
  349.   R_memset ((POINTER)digestInfo, 0, sizeof (digestInfo));
  350.  
  351.   return (status);
  352. }
  353.  
  354. int R_DigestBlock (digest, digestLen, block, blockLen, digestAlgorithm)
  355. unsigned char *digest;                                    /* message digest */
  356. unsigned int *digestLen;                        /* length of message digest */
  357. unsigned char *block;                                              /* block */
  358. unsigned int blockLen;                                   /* length of block */
  359. int digestAlgorithm;                            /* message-digest algorithm */
  360. {
  361.   MD2_CTX md2Context;
  362.   MD5_CTX md5Context;
  363.   int status;
  364.   
  365.   status = 0;
  366.   
  367.   switch (digestAlgorithm) {
  368.   case DA_MD2:
  369.     MD2Init (&md2Context);
  370.     MD2Update (&md2Context, block, blockLen);
  371.     MD2Final (digest, &md2Context);
  372.     *digestLen = 16;
  373.     break;
  374.  
  375.   case DA_MD5:
  376.     MD5Init (&md5Context);
  377.     MD5Update (&md5Context, block, blockLen);
  378.     MD5Final (digest, &md5Context);
  379.     *digestLen = 16;
  380.     break;
  381.   
  382.   default:
  383.     status = RE_DIGEST_ALGORITHM;
  384.   }
  385.   
  386.   return (status);
  387. }
  388.  
  389. /* Assumes digestAlgorithm is DA_MD2 or DA_MD5 and digest length is 16.
  390.  */
  391. static void R_EncodeDigestInfo (digestInfo, digestAlgorithm, digest)
  392. unsigned char *digestInfo;                           /* DigestInfo encoding */
  393. int digestAlgorithm;                            /* message-digest algorithm */
  394. unsigned char *digest;                                    /* message digest */
  395. {
  396.   R_memcpy 
  397.     ((POINTER)digestInfo, (POINTER)DIGEST_INFO_A, DIGEST_INFO_A_LEN);
  398.   
  399.   digestInfo[DIGEST_INFO_A_LEN] =
  400.     (digestAlgorithm == DA_MD2) ? (unsigned char)2 : (unsigned char)5;
  401.  
  402.   R_memcpy 
  403.     ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1], (POINTER)DIGEST_INFO_B,
  404.      DIGEST_INFO_B_LEN);
  405.   
  406.   R_memcpy 
  407.     ((POINTER)&digestInfo[DIGEST_INFO_A_LEN + 1 + DIGEST_INFO_B_LEN],
  408.      (POINTER)digest, 16);
  409. }
  410.  
  411. static void R_EncryptPEMBlock
  412.   (encryptedBlock, encryptedBlockLen, block, blockLen, key, iv)
  413. unsigned char *encryptedBlock;                  /* encrypted, encoded block */
  414. unsigned int *encryptedBlockLen;                                  /* length */
  415. unsigned char *block;                                              /* block */
  416. unsigned int blockLen;                                   /* length of block */
  417. unsigned char key[8];                                            /* DES key */
  418. unsigned char iv[8];                           /* DES initialization vector */
  419. {
  420.   DES_CBC_CTX context;
  421.   unsigned char encryptedPart[24], lastPart[24];
  422.   unsigned int i, lastPartLen, len, padLen;
  423.   
  424.   DES_CBCInit (&context, key, iv, 1);
  425.  
  426.   for (i = 0; i < blockLen/24; i++) {
  427.     DES_CBCUpdate (&context, encryptedPart, &block[24*i], 24);
  428.     /* len is always 32 */
  429.     R_EncodePEMBlock (&encryptedBlock[32*i], &len, encryptedPart, 24);
  430.   }
  431.   
  432.   padLen = 8 - (blockLen % 8);
  433.   lastPartLen = blockLen - 24*i + padLen;
  434.   R_memcpy ((POINTER)lastPart, (POINTER)&block[24*i], lastPartLen - padLen);
  435.   R_memcpy
  436.     ((POINTER)&lastPart[lastPartLen - padLen], PADDING[padLen], padLen);
  437.   DES_CBCUpdate (&context, encryptedPart, lastPart, lastPartLen);
  438.   R_EncodePEMBlock 
  439.     (&encryptedBlock[32*i], &len, encryptedPart, lastPartLen);
  440.   *encryptedBlockLen = 32*i + len;
  441.  
  442.   DES_CBCFinal (&context);
  443.   
  444.   /* Zeroize sensitive information.
  445.    */
  446.   R_memset ((POINTER)lastPart, 0, sizeof (lastPart));
  447. }
  448.  
  449. static int R_DecryptPEMBlock
  450.   (block, blockLen, encryptedBlock, encryptedBlockLen, key, iv)
  451. unsigned char *block;                                              /* block */
  452. unsigned int *blockLen;                                  /* length of block */
  453. unsigned char *encryptedBlock;                  /* encrypted, encoded block */
  454. unsigned int encryptedBlockLen;                                   /* length */
  455. unsigned char key[8];                                            /* DES key */
  456. unsigned char iv[8];                           /* DES initialization vector */
  457. {
  458.   DES_CBC_CTX context;
  459.   int status;
  460.   unsigned char encryptedPart[24], lastPart[24];
  461.   unsigned int i, lastPartLen, len, padLen;
  462.   
  463.   if (encryptedBlockLen < 1)
  464.     return (RE_LEN);
  465.  
  466.   DES_CBCInit (&context, key, iv, 0);
  467.   
  468.   status = 0;
  469.   
  470.   do {
  471.     for (i = 0; i < (encryptedBlockLen-1)/32; i++) {
  472.       /* len is always 24 */
  473.       if (status = R_DecodePEMBlock
  474.           (encryptedPart, &len, &encryptedBlock[32*i], 32))
  475.         break;
  476.       DES_CBCUpdate (&context, &block[24*i], encryptedPart, 24);
  477.     }
  478.     if (status)
  479.       break;
  480.   
  481.     len = encryptedBlockLen - 32*i;
  482.     if (status = R_DecodePEMBlock
  483.         (encryptedPart, &lastPartLen, &encryptedBlock[32*i], len))
  484.       break;
  485.  
  486.     if (lastPartLen % 8) {
  487.       status = RE_DATA;
  488.       break;
  489.     }
  490.     
  491.     DES_CBCUpdate (&context, lastPart, encryptedPart, lastPartLen);
  492.  
  493.     padLen = lastPart[lastPartLen - 1];
  494.     if (padLen > 8) {
  495.       status = RE_DATA;
  496.       break;
  497.     }
  498.     if (R_memcmp 
  499.         ((POINTER)&lastPart[lastPartLen - padLen], PADDING[padLen], padLen)) {
  500.       status = RE_DATA;
  501.       break;
  502.     }
  503.     
  504.     R_memcpy ((POINTER)&block[24*i], (POINTER)lastPart, lastPartLen - padLen);
  505.     *blockLen = 24*i + lastPartLen - padLen;
  506.  
  507.   } while (0);
  508.  
  509.   DES_CBCFinal (&context);
  510.  
  511.   /* Zeroize sensitive information.
  512.    */
  513.   R_memset ((POINTER)lastPart, 0, sizeof (lastPart));
  514.  
  515.   return (status);
  516. }
  517.